/**
 * for in 循环机制
 * 优先迭代数字属性
 * 会遍历所有私有和公有的可枚举属性[性能最差的循环；公有的属性一般是不需要迭代的]
 * 无法迭代Symbol类型额私有属性
 * 
 * for of 循环机制
 * Iterator迭代器
 * for of原理
 * 让对象也可以使用for of循环
 */

Object.prototype.AAA = 100
Object.prototype[10] = 200
let obj = {
    name: 'zhao',
    age: 12,
    [Symbol('AAA')]: 100,
    0: 10,
    1: 20
};

for(let key in obj) {
    if(!obj.hasOwnProperty(key)) break; // 避免迭代公有属性，hasOwnProperty只找私有属性
    console.log(key) // 0 1 name age 10 AAA 
}

// Object.keys() 获取所有非Symbol类型的私有属性
let keys = Object.getOwnPropertyNames(obj); // 获取所有非Symbol类型的私有属性，结果是个数组，数组中包含属性名
keys = keys.concat(Object.getOwnPropertySymbols(obj)); // 拼接上所有symbol类型的私有属性
console.log(keys)
keys.forEach(key => {
    console.log(key, obj[key]); // 0 1 name age Symbol('AAA')
});

// 封装遍历对象的方法，不用for in
// obj 默认是个纯对象
const eachObject = function eachObject(obj, callback) {

}


// 遍历器是一种机制（接口），为不同的数据结构提供统一的访问机制，任何数据结构只要部署Iterator接口，就可以完成遍历操作【for of循环】，依次处理该数据结构的所有成员
// 拥有next方法用于一次遍历数据结构的成员
// 每一次遍历返回的结果是一个对象{done: false, value: xxx}
// done 记录是否遍历完成
// value 当前遍历的结果


// 迭代器规范
class Interator {
    constructor(assemble) {
        this.assemble = assemble
        this.index = 0
    }
    next() {
        let { index, assemble } = this
        if(index > assemble.length) {
            return {
                done: true,
                value: undefined
            }
        }
        return {
            done: false,
            value: assemble[this.index++]
        }
    }
}

let itor = new Interator([10, 20, 30, 40])
console.log(itor.next())
console.log(itor.next())
console.log(itor.next())
console.log(itor.next())
console.log(itor.next())

// 拥有Symbol.iterator属性的数据结构，被称为可被遍历的，可以基于for of循环处理
// 数组
  // 重写数组的Symbol.iterator方法
  arr[Symbol.iterator] = function() {
    let self = this, index = 0
    return {
        next() {
            if(index > self.length - 1) {
                return {
                    done: true,
                    value: undefined
                }
            }
            return {
                done: false,
                value: self[index++]
            }
        }
    }
  }
let arr = [10, 20, 30, 40, 50]
for(let item of arr) {
    // 首先获取arr[Symbol.iterator]属性的函数，并且把它执行，拿到一个itor迭代器对象
    // 每一轮循环 都是执行一次 itor.next() -> {done: false, value: 10}
    console.log(item)
}

// 部分类数组 arguments/NodeList/HTMLCollection
// String
// Set
// Map



// obj使用for of循环
Object.prototype[Symbol.iterator] = function() {
    let obj = this,
        keys = Object.getOwnPropertyNames(obj).concat(Object.getOwnPropertySymbols(obj)),
        index = 0;
    return {
        next() {
            if(index > keys.length - 1) {
                return {
                    done: true,
                    value: undefined
                }
            }
            return {
                done: false,
                value: obj[keys[index++]]
            }
        }
    }
}
let obj1 = {
    name: 'zhao',
    age: 20,
    sex: 'male'
}
for(let item in obj1) {
    console.log(item)
}


var isPromise = function isPromise(x) {
    if(x!==null && /^(object|function)$/.test(typeof x)) {
        var then;
        try {
            then = x.then
        }catch(err) {
            return false
        }
        if(typeof then === 'function') return true
    }
    return false
}